
package com.hlkj.pay.app.merchant.ext.impl.yytpay.ext;
/*
 * Hlpay-Plus aggregate payment system.
 * Copyright (c) 2024-2025 Hlpay Team Copyright has the right of final interpretation.
 */

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Repository;
import org.springframework.util.StringUtils;

import com.hlkj.framework.common.pojo.CommonResult;
import com.hlkj.framework.common.util.json.JsonUtils;
import com.hlkj.pay.app.merchant.ext.dto.order.ChannelPayOrderQueryContext;
import com.hlkj.pay.app.merchant.ext.dto.order.ChannelRefundPayOrderContext;
import com.hlkj.pay.app.merchant.ext.impl.yytpay.constant.YytPayAppChannelParams;
import com.hlkj.pay.app.merchant.ext.impl.yytpay.dto.YytPayConfig;
import com.hlkj.pay.app.merchant.ext.impl.yytpay.dto.resp.YytOrderQueryDataResp;
import com.hlkj.pay.app.merchant.ext.impl.yytpay.dto.resp.YytOrderQueryResp;
import com.hlkj.pay.app.merchant.ext.impl.yytpay.dto.resp.YytOrderResp;
import com.hlkj.pay.app.merchant.ext.impl.yytpay.handler.YytPayCommonParamsHandle;
import com.hlkj.pay.enums.PayOrderEnums;
import com.hlkj.pay.infrastructure.model.merchant.MerchantAppChannelDO;
import com.hlkj.pay.infrastructure.model.order.PayOrderDO;
import com.hlkj.pay.infrastructure.model.order.RefundOrderDO;
import com.hlkj.pay.infrastructure.model.pay.PayWayDO;
import com.hlkj.pay.util.DateUtils;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * 银盈通支付 正扫 反扫 通用处理
 *
 * @author HlpayTeam
 * @date 2024/10/11 16:22
 */
@Slf4j
@Repository
@RequiredArgsConstructor
public class YytPaySceneCommonPayOrder {

    @Value("${hlkj.domain}")
    public String domain;

    @Autowired
    private YytPayCommonParamsHandle yytPayCommonParamsHandle;

    /**
     * 银盈通支付查询支付订单
     *
     * @param channelPayOrderContext
     */
    public void commonQueryChannelPayOrder(ChannelPayOrderQueryContext channelPayOrderContext) {

        CommonResult<YytPayConfig> yytPayConfigCommonResult = yytPayCommonParamsHandle.yytPayConfig(channelPayOrderContext.getProviderChannelConfigDO(),
                channelPayOrderContext.isTest());
        if (!yytPayConfigCommonResult.isSuccess()) {
            channelPayOrderContext.setRemark(yytPayConfigCommonResult.getMsg());
            channelPayOrderContext.setProcessStatus(false);
            return;
        }
        // 支付方式信息
        PayWayDO payWayDO = channelPayOrderContext.getPayWayDO();
        String payway = yytPayCommonParamsHandle.getPayWay(payWayDO);
        // 支付订单信息
        PayOrderDO payOrderDO = channelPayOrderContext.getPayOrderDO();
        // 商户通道
        MerchantAppChannelDO merchantAppChannelDO = channelPayOrderContext.getMerchantAppChannelDO();
        // 银盈通配置信息
        YytPayConfig yytPayConfig = yytPayConfigCommonResult.getData();
        try {
            YytPayAppChannelParams yytPayAppChannelParams = JsonUtils.parseObject(merchantAppChannelDO.getAppConfigJson(), YytPayAppChannelParams.class);

            Map<String,String> reqData = new HashMap<>();
            reqData.put("merchant_number",yytPayAppChannelParams.getMchId());
            reqData.put("order_number", payOrderDO.getPayOrderNo());
            reqData.put("trans_type", "pay");

            log.info("银盈通 订单查询  请求参数 :{}", JsonUtils.toJsonString(reqData));
            YytOrderResp result = yytPayCommonParamsHandle.sendPostRequest("https://gc-gw.gomepay.com/gpayCashApi", JSONUtil.toJsonStr(reqData), "cash-api@gcash.trade.query",yytPayConfig,payOrderDO,"4",payway);
            log.info("银盈通 订单查询  返回参数 :{}", result);
            if(result == null ||!"000000".equals(result.getCode())) {
                channelPayOrderContext.setProcessStatus(Boolean.FALSE);
                channelPayOrderContext.setRemark(result.getMsg());
                return;
            }
            // 结果转对象
            YytOrderQueryResp transQueryRes = JSONUtil.toBean(result.getData(),YytOrderQueryResp.class);
            PayOrderDO updartePayOrderDO = new PayOrderDO();
            /**
             * 00 成功
             * 01 待支付
             * 02 支付中
             * 03 担保中
             * 05 失败
             * 06 关闭
             */
            switch (transQueryRes.getStatus()) {
                case "01":
                case "02":
                case "03":
                    updartePayOrderDO.setState(PayOrderEnums.PAY_ORDER_STATUS.PAYING.getCode());
                    updartePayOrderDO.setBankMsg("");
                    break;
                case "00":
                    updartePayOrderDO.setState(PayOrderEnums.PAY_ORDER_STATUS.SUCCESS.getCode());
                    updartePayOrderDO.setBankMsg("");
                    break;
                case "06":
                    updartePayOrderDO.setState(PayOrderEnums.PAY_ORDER_STATUS.CLOSE.getCode());
                    break;
                case "05":
                    updartePayOrderDO.setState(PayOrderEnums.PAY_ORDER_STATUS.FAIL.getCode());
                    break;
            }

            if (StringUtils.hasText(transQueryRes.getEnd_time())) {
                try {
                    updartePayOrderDO.setSuccessTime(DateUtils.shanghaiDate(transQueryRes.getEnd_time(), DatePattern.NORM_DATETIME_PATTERN));
                }
                catch (Exception e) {
                    log.error("银盈通订单查询返回 时间格式化错误 dateTime:{},message:{}", transQueryRes.getEnd_time(), e.getMessage());
                }
            }
            updartePayOrderDO.setInsOrderNo(transQueryRes.getOrder_id());
            if (StrUtil.isNotEmpty(transQueryRes.getTotal_amount())) {
                updartePayOrderDO.setPayAmount(new BigDecimal(transQueryRes.getTotal_amount()));
            }
            if (StrUtil.isNotEmpty(transQueryRes.getReceipt_amount())) {
                updartePayOrderDO.setSettlementAmount(new BigDecimal(transQueryRes.getReceipt_amount()));
            }

            if(StrUtil.isNotEmpty(transQueryRes.getBiz_content())){
                Map<String,Object> bizMap = JSONUtil.toBean(transQueryRes.getBiz_content(),Map.class);
                if(MapUtil.isNotEmpty(bizMap) && bizMap.get("data") != null){
                    List<YytOrderQueryDataResp> queryDataResp = JSONUtil.toList(JSONUtil.toJsonStr(bizMap.get("data")),YytOrderQueryDataResp.class);
                    if(CollUtil.isNotEmpty(queryDataResp)){
                        updartePayOrderDO.setChannelOrderNo(queryDataResp.get(0).getBank_order_id());
                        updartePayOrderDO.setUserId(queryDataResp.get(0).getBank_user_id());
                    }
                }
            }
            channelPayOrderContext.setUpdartePayOrderDO(updartePayOrderDO);
        }catch (Exception e){
            e.printStackTrace();
            log.error("银盈通查询支付订单请求失败 message:{}", e.getMessage(), e);
            channelPayOrderContext.setRemark("银盈通查询支付订单请求失败,失败信息" + e.getMessage());
            channelPayOrderContext.setProcessStatus(Boolean.FALSE);
        }
    }

    /**
     * 银盈通支付关闭订单
     *
     * @param channelClosePayOrderContext
     */
    public void commonCloseChannelPayOrder(ChannelPayOrderQueryContext channelClosePayOrderContext) {
        PayOrderDO updartePayOrderDO = new PayOrderDO();
        updartePayOrderDO.setState(PayOrderEnums.PAY_ORDER_STATUS.SUCCESS.getCode());
        channelClosePayOrderContext.setUpdartePayOrderDO(updartePayOrderDO);
    }

    /**
     * 银盈通支付查询关闭订单状态
     *
     * @param channelPayOrderQueryContext
     */
    public void  commonQueryChannelClosePayOrder(ChannelPayOrderQueryContext channelPayOrderQueryContext) {
        PayOrderDO updartePayOrderDO = new PayOrderDO();
        updartePayOrderDO.setState(PayOrderEnums.PAY_ORDER_STATUS.CLOSE.getCode());
        channelPayOrderQueryContext.setUpdartePayOrderDO(updartePayOrderDO);
    }

    /**
     * 银盈通支付订单退款
     *
     * @param channelRefundPayOrderContext
     */
    public void commonRefundChannelPayOrder(ChannelRefundPayOrderContext channelRefundPayOrderContext) {
        CommonResult<YytPayConfig> yytPayConfigCommonResult = yytPayCommonParamsHandle.yytPayConfig(channelRefundPayOrderContext.getProviderChannelConfigDO(),
                channelRefundPayOrderContext.isTest());
        if (!yytPayConfigCommonResult.isSuccess()) {
            channelRefundPayOrderContext.setRemark(yytPayConfigCommonResult.getMsg());
            channelRefundPayOrderContext.setProcessStatus(false);
            return;
        }
        // 支付方式信息
        PayWayDO payWayDO = channelRefundPayOrderContext.getPayWayDO();
        String payway = yytPayCommonParamsHandle.getPayWay(payWayDO);
        // 支付订单信息
        PayOrderDO payOrderDO = channelRefundPayOrderContext.getPayOrderDO();
        // 退款信息
        RefundOrderDO refundOrderDO = channelRefundPayOrderContext.getRefundOrderDO();
        // 商户通道
        MerchantAppChannelDO merchantAppChannelDO = channelRefundPayOrderContext.getMerchantAppChannelDO();
        // 银盈通配置信息
        YytPayConfig yytPayConfig = yytPayConfigCommonResult.getData();
        try {
            YytPayAppChannelParams yytPayAppChannelParams = JsonUtils.parseObject(merchantAppChannelDO.getAppConfigJson(), YytPayAppChannelParams.class);

            Map<String,String> reqData = new HashMap<>();
            reqData.put("merchant_number",yytPayAppChannelParams.getMchId());
            reqData.put("order_number", refundOrderDO.getRefundOrderNo());
            reqData.put("old_order_id", payOrderDO.getInsOrderNo());
            reqData.put("refund_amount", NumberUtil.roundStr(refundOrderDO.getRefundAmount().doubleValue(),2));
            reqData.put("remark", refundOrderDO.getRefundReason());
            reqData.put("notify_url", channelRefundPayOrderContext.getNotifyUrl());

            log.info("银盈通 订单退款  请求参数 :{}", JsonUtils.toJsonString(reqData));
            YytOrderResp result = yytPayCommonParamsHandle.sendPostRequest("https://gc-gw.gomepay.com/gpayCashApi", JSONUtil.toJsonStr(reqData), "cash-api@gcash.trade.refund",yytPayConfig,payOrderDO,"4",payway);
            log.info("银盈通 订单退款  返回参数 :{}", result);
            if(result == null ||!"900001".equals(result.getCode())) {
                channelRefundPayOrderContext.setProcessStatus(Boolean.FALSE);
                channelRefundPayOrderContext.setRemark(result.getMsg());
            }
        }catch (Exception e){
            log.error("银盈通支付退款请求失败 message:{}", e.getMessage(), e);
            channelRefundPayOrderContext.setRemark("银盈通支付退款请求失败,失败信息" + e.getMessage());
            channelRefundPayOrderContext.setProcessStatus(Boolean.FALSE);
        }
    }

    /**
     * 银盈通支付订单退款状态查询
     *
     * @param channelRefundPayOrderContext
     */
    public void commonQueryRefundChannelPayOrder(ChannelRefundPayOrderContext channelRefundPayOrderContext) {

        CommonResult<YytPayConfig> yytPayConfigCommonResult = yytPayCommonParamsHandle.yytPayConfig(channelRefundPayOrderContext.getProviderChannelConfigDO(),
                channelRefundPayOrderContext.isTest());
        if (!yytPayConfigCommonResult.isSuccess()) {
            channelRefundPayOrderContext.setRemark(yytPayConfigCommonResult.getMsg());
            channelRefundPayOrderContext.setProcessStatus(false);
            return;
        }
        // 支付方式
        PayWayDO payWayDO = channelRefundPayOrderContext.getPayWayDO();
        String payway = yytPayCommonParamsHandle.getPayWay(payWayDO);
        // 支付订单信息
        PayOrderDO payOrderDO = channelRefundPayOrderContext.getPayOrderDO();
        // 退款信息
        RefundOrderDO refundOrderDO = channelRefundPayOrderContext.getRefundOrderDO();
        // 商户通道
        MerchantAppChannelDO merchantAppChannelDO = channelRefundPayOrderContext.getMerchantAppChannelDO();
        // 银盈通配置信息
        YytPayConfig yytPayConfig = yytPayConfigCommonResult.getData();
        try {
            YytPayAppChannelParams yytPayAppChannelParams = JsonUtils.parseObject(merchantAppChannelDO.getAppConfigJson(), YytPayAppChannelParams.class);

            Map<String,String> reqData = new HashMap<>();
            reqData.put("merchant_number",yytPayAppChannelParams.getSubMchId());
            reqData.put("order_number", refundOrderDO.getRefundOrderNo());
            reqData.put("trans_type", "refund");

            log.info("银盈通 订单退款查询  请求参数 :{}", JsonUtils.toJsonString(reqData));
            YytOrderResp result = yytPayCommonParamsHandle.sendPostRequest("https://gc-gw.gomepay.com/gpayCashApi", JSONUtil.toJsonStr(reqData), "cash-api@gcash.trade.query",yytPayConfig,payOrderDO,"4",payway);
            log.info("银盈通 订单退款查询  返回参数 :{}", result);
            if(result == null ||!"000000".equals(result.getCode())) {
                channelRefundPayOrderContext.setProcessStatus(Boolean.FALSE);
                channelRefundPayOrderContext.setRemark(result.getMsg());
                return;
            }
            // 结果转对象
            YytOrderQueryResp transQueryRes = JSONUtil.toBean(result.getData(),YytOrderQueryResp.class);
            RefundOrderDO updateRefundOrderDO = new RefundOrderDO();
            /**
             * 00 成功
             * 02 退货中
             * 05 失败
             */
            switch (transQueryRes.getStatus()){
                case "02":
                    updateRefundOrderDO.setRefundStatus(PayOrderEnums.REFUND_STATUS.REFUNDING.getCode());
                    break;
                case "00":
                    updateRefundOrderDO.setRefundStatus(PayOrderEnums.REFUND_STATUS.REFUND.getCode());
                    updateRefundOrderDO.setActualRefundAmount(new BigDecimal(transQueryRes.getReceipt_amount()));
                    if(StrUtil.isNotEmpty(transQueryRes.getEnd_time())){
                        updateRefundOrderDO.setSuccessTime(DateUtils.shanghaiDate(transQueryRes.getEnd_time(), DatePattern.NORM_DATETIME_PATTERN));
                    }
                    break;
                case "05":
                    updateRefundOrderDO.setRefundStatus(PayOrderEnums.REFUND_STATUS.FAIL.getCode());
                    break;
            }
            channelRefundPayOrderContext.setRefundOrderDO(updateRefundOrderDO);

        }catch (Exception e){
            log.error("银盈通支付查询退款请求失败 message:{}", e);
            channelRefundPayOrderContext.setRemark("银盈通支付查询退款请求失败,失败信息" + e.getMessage());
            channelRefundPayOrderContext.setProcessStatus(Boolean.FALSE);
        }
    }


    public Integer expireMinute(Long time) {
        if (time == null) {
            return 30;
        }
        return (int) (time - System.currentTimeMillis()) / 1000 / 60;
    }


    public String reqTime() {
        return DateUtils.getDateString("yyyyMMddHHmmss");
    }

    public String openapiDomain(boolean test) {
        // 测试环境：https://test.wsmsd.cn/sit/api/v2/mms/openApi/wechatParamConf
        // 生产环境：https://s2.lakala.com/api/v2/mms/openApi/wechatParamConf
        if (test) {
            return "https://test.wsmsd.cn/sit";
        }
        else {
            return "https://s2.lakala.com";
        }
    }
}
